package com.backpackerxl.blog.service.impl;

import com.backpackerxl.blog.dao.TagRepository;
import com.backpackerxl.blog.model.Blog;
import com.backpackerxl.blog.model.Tag;
import com.backpackerxl.blog.model.Type;
import com.backpackerxl.blog.service.TagService;
import com.backpackerxl.blog.vomodel.BlogCount;
import com.backpackerxl.blog.vomodel.KeyWordsQuery;
import com.backpackerxl.blog.web.NotFoundException;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Author by：Backpackersxl
 * Date: 2021/5/5/005
 * Time: 23:39
 **/
@Service
public class TagServiceImp implements TagService {
    private final TagRepository tagRepository;

    public TagServiceImp(TagRepository tagRepository) {
        this.tagRepository = tagRepository;
    }

    /**
     * 保存
     *
     * @param tag 标签
     * @return 保存
     */
    @Transactional
    @Override
    public Tag saveTag(Tag tag) {
        return tagRepository.save(tag);
    }

    /**
     * 查询
     *
     * @param id 博客id
     * @return 标签
     */
    @Transactional
    @Override
    public Tag getTag(Long id) {
        return tagRepository.findById(id).orElse(null);
    }

    @Override
    public Tag getTagByName(String name) {
        return tagRepository.findByName(name);
    }

    /**
     * 分页查询
     *
     * @param pageable 分页器
     * @return 分页标签
     */
    @Transactional
    @Override
    public Page<Tag> listTag(Pageable pageable) {
        return tagRepository.findAll(pageable);
    }

    /**
     * 更新
     *
     * @param id  blog id
     * @param tag 标签
     * @return 标签
     */
    @SneakyThrows
    @Transactional
    @Override
    public Tag updateTag(Long id, Tag tag) {
        Tag t = tagRepository.findById(id).orElse(null);
        if (t == null) {
            throw new NotFoundException("不存在该类型");
        }
        BeanUtils.copyProperties(tag, t);

        return tagRepository.save(t);
    }

    /**
     * 删除
     *
     * @param id blog id
     */
    @Transactional
    @Override
    public void deleteTag(Long id) {
        tagRepository.deleteById(id);
    }

    @Override
    public List<Tag> listTag() {
        return tagRepository.findAll();
    }

    @Override
    public List<Tag> listTag(String ids) {
        List<Long> longs = convertToList(ids);
        return longs == null ? new ArrayList<>() : tagRepository.findAllById(longs);
    }

    @Override
    public List<Tag> listTagTop(Integer size) {
        Sort sort = Sort.by(Sort.Direction.DESC, "blogs.size");
        Pageable pageable = PageRequest.of(0, size, sort);
        return tagRepository.findTop(pageable);
    }

    @Override
    public List<BlogCount> listTypeCount() {
        return tagRepository.findCountTag();
    }

    @Override
    public Page<Tag> listTags(Pageable pageable, KeyWordsQuery key) {
        return tagRepository.findAll((Specification<Tag>) (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (!"".equals(key.getKeywords()) && key.getKeywords() != null) {
                predicates.add(criteriaBuilder.like(root.get("name"), "%" + key.getKeywords() + "%"));
            }
            query.where(predicates.toArray(new Predicate[0]));
            return null;
        }, pageable);
    }

    /**
     * 将前端传回来的字符串转储存为集合
     *
     * @param ids 字符串id
     * @return id List
     */
    private List<Long> convertToList(String ids) {
        if (!"".equals(ids) && ids != null) {
            return Arrays.stream(ids.split(",")).map(Long::new).collect(Collectors.toList());
        } else {
            return null;
        }
    }
}
